package cn.tb.ymcc.service.impl;

import cn.tb.ymcc.domain.CourseType;
import cn.tb.ymcc.dto.CourseTypeMbxDto;
import cn.tb.ymcc.mapper.CourseTypeMapper;
import cn.tb.ymcc.result.JSONResult;
import cn.tb.ymcc.service.ICourseTypeService;
import cn.tb.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author tangbo
 * @since 2022-07-20
 */
@Service
@Slf4j
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    /**
     * 无限级树缓存
     * @return
     */

    @Override
    @Cacheable(cacheNames = "coursetypetree",key = "'tree'")
    public List<CourseType> treeData() {
        List<CourseType> tree = tree();
        return tree;
    }

    /**
     * 备份无限级树缓存
     * @return
     */
    public List<CourseType> treeData2() {

        //1.先查询Redis中有没有无限级缓存树
        String courseTypeTree = "coursetypetree";
        Object obj = redisTemplate.opsForValue().get(courseTypeTree);
        if(obj!=null){
            log.info("redis");
            //2.不为空，就说明查到了，直接返回
            return (List<CourseType>) obj;
        }
        //3.没有，先查询数据库，再存入Redis
        log.info("mysql");
        List<CourseType> tree = tree();
        redisTemplate.opsForValue().set(courseTypeTree,tree);
        return tree;
    }

    /**
     * 课程类型无限级树
     * @return
     */
    public List<CourseType> tree() {
        //1.查询出所有数据，放到内存
        List<CourseType> courseTypes = selectList(null);
        HashMap<Long, CourseType> allTypes = new HashMap<>();
        courseTypes.forEach(type->{
            allTypes.put(type.getId(),type);
        });
        ArrayList<CourseType> firstList = new ArrayList<>();
        for(CourseType type:courseTypes){
            //2.查找出顶级firstList，返回List
            if(type.getPid()==null || type.getPid().intValue()==0){
                firstList.add(type);
            }else {
                //3.所有不是顶级的都找到自己的上级，把自己放到上级的children中
                allTypes.get(type.getPid()).getChildren().add(type);
            }
        }
        return firstList;
    }

    /**
     * 课程分类面包屑
     *
     * 1.参数校验
     * 2.根据当前课程分类ID查询课程分类详情
     * 3.得到id的path，分割path得到多个id的集合
     * 4.根据集合批量查询出多个分类对象
     * 5.循环分类，每次循环需要创建一个mbxDto，把当前分类装到ownerCourseType
     * 6.为当前分类查询同级分类列表，装到mbxDto的otherCourseTypes
     * @param courseId
     * @return
     */
    @Override
    public JSONResult crumbs(Long courseId) {
        ArrayList<CourseTypeMbxDto> courseTypeMbxDtos = new ArrayList<>();
        CourseType courseType = selectById(courseId);
        AssertUtil.isNotNull(courseType,"课程类型为空");
        //得到id的path，分割path得到多个id的集合
        String[] path = courseType.getPath().split("\\.");
        List<CourseType> courseTypes = selectBatchIds(Arrays.asList(path));
        //循环分类，每次循环需要创建一个mbxDto，把当前分类装到ownerCourseType
        courseTypes.forEach(courseTypesTmp->{
            CourseTypeMbxDto mbxDto = new CourseTypeMbxDto();
            mbxDto.setOwnerCourseType(courseTypesTmp);
            EntityWrapper<CourseType> wrapper = new EntityWrapper<>();
            wrapper.eq("pid",courseTypesTmp.getPid());
            List<CourseType> typeList = selectList(wrapper);
            mbxDto.setOtherCourseTypes(typeList);
            courseTypeMbxDtos.add(mbxDto);
        });
        return JSONResult.success(courseTypeMbxDtos);
    }



    @Override
    @CacheEvict(cacheNames = "coursetypetree",key = "'tree'")
    public boolean updateById(CourseType entity) {
        boolean update = super.updateById(entity);
        /*if(update){
            redisTemplate.delete(courseTypeTree);
        }*/
        return update;
    }

    @Override
    @CacheEvict(cacheNames = "coursetypetree",key = "'tree'")
    public boolean insert(CourseType entity) {
        boolean insert = super.insert(entity);
        /*if(insert){
            redisTemplate.delete(courseTypeTree);
        }*/
        return insert;
    }


    @Override
    @CacheEvict(cacheNames = "coursetypetree",key = "'tree'")
    public boolean deleteById(Serializable id) {
        boolean delete = super.deleteById(id);
        /*if(delete){
            redisTemplate.delete(courseTypeTree);
        }*/
        return delete;
    }
}
